﻿//=============================================================== 
// filename :Subway  
// created by herb at 2018/2/10 10:15:46  
// personal homepage:http://www.xiaoboke.net  
//===============================================================
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace SubwayHelper
{
    /// <summary>
    /// 封装了对地铁线路各种操作的实体
    /// </summary>
    public static class Subway
    {
        /// <summary>
        /// 装载地铁线路数据的xml文档
        /// </summary>
        private static XDocument _doc;

        /// <summary>
        /// 当前城市
        /// </summary>
        private static CityEnum _currentCity;

        /// <summary>
        /// 包含当前城市所有线路的集合
        /// </summary>
        public static List<SubwayLine> AllSubwayLines { get; private set; }

        /// <summary>
        /// 初始化地铁线路数据
        /// </summary>
        /// <param name="city">城市</param>
        public static void InitSubwayLine(CityEnum city)
        {
            if (AllSubwayLines != null && AllSubwayLines.Any() && _currentCity == city) return;
            _currentCity = city;
            var xmlName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "xml/" + city.ToString() + ".xml");
            _doc = XDocument.Load(xmlName);
            AllSubwayLines = _doc.Root.Elements().Select(x =>
            {
                var line = new SubwayLine
                {
                    No = x.Attribute("No").Value,
                    Name = x.Attribute("Name").Value,
                    IsRound = x.Attribute("IsRound") == null ? false : bool.Parse(x.Attribute("IsRound").Value),
                    Stations = x.Elements().Select((y, i) => new Station
                    {
                        Index = i,
                        Name = y.Attribute("Name").Value,
                        LineNo = x.Attribute("No").Value,
                        CanTransfer = y.Attribute("CanTransfer") == null ? false : bool.Parse(y.Attribute("CanTransfer").Value),
                        TransferNo = y.Attribute("TransferNo") == null ? null : y.Attribute("TransferNo").Value
                    }).ToList()
                };
                var translines = line.GetTransStations().Select(z => z.TransferNo.Split(',')).ToList();
                foreach (var transline in translines)
                {
                    foreach (var li in transline)
                    {
                        line.TransferLines.Add(li);
                    }
                }
                line.TransferLines = line.TransferLines.Distinct().ToList();
                return line;
            }).ToList();
        }

        /// <summary>
        /// 根据线路编号获取线路
        /// </summary>
        /// <param name="lineNo"></param>
        /// <returns></returns>
        public static SubwayLine GetLine(object lineNo)
        {
            return AllSubwayLines.SingleOrDefault(x => x.No.IsSame(lineNo.ToString()));
        }

        /// <summary>
        /// 根据两点确定唯一线路（正常情况下经过两点有且只有一条线路）
        /// </summary>
        /// <param name="station1"></param>
        /// <param name="station2"></param>
        /// <returns></returns>
        public static SubwayLine GetLine(string station1, string station2)
        {
            return IsSameLine(station1, station2) ? GetAcrossLines(station1, station2).First() : null;
        }

        /// <summary>
        /// 根据站点名称获取唯一站点（不获取可换乘站点）
        /// </summary>
        /// <param name="stationName"></param>
        /// <returns></returns>
        public static Station GetStation(string stationName)
        {
            return !IsTransferStation(stationName) ? GetAcrossLines(stationName).First().Stations.FirstOrDefault(x => x.Name.IsSame(stationName)) : null;
        }

        /// <summary>
        /// 获取经过本站点的所有线路
        /// </summary>
        /// <param name="stationName"></param>
        /// <returns></returns>
        public static List<SubwayLine> GetAcrossLines(string stationName)
        {
            return AllSubwayLines.Where(x => x.Stations.Any(y => y.Name.IsSame(stationName))).ToList();
        }

        /// <summary>
        /// 获取站点在指定线路上的索引
        /// </summary>
        /// <param name="stationName"></param>
        /// <param name="lineNo"></param>
        /// <returns></returns>
        public static int GetIndexOnLine(string stationName, object lineNo)
        {
            return GetIndexOnLine(stationName, GetLine(lineNo));
        }

        /// <summary>
        /// 获取站点在指定线路上的索引
        /// </summary>
        /// <param name="stationName"></param>
        /// <param name="line"></param>
        /// <returns></returns>
        public static int GetIndexOnLine(string stationName, SubwayLine line)
        {
            if (line.Stations.Exists(x => x.Name.IsSame(stationName)))
            {
                return line.Stations.FindIndex(x => x.Name.IsSame(stationName));
            }
            return -1;
        }

        /// <summary>
        /// 获取线路上所有的换乘站
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        public static List<Station> GetTransStations(this SubwayLine line)
        {
            return line.Stations.Where(x => x.CanTransfer).ToList();
        }

        /// <summary>
        /// 获取距离本站最近的站点 || 获取距离本站最近的换乘站点
        /// </summary>
        /// <param name="stationName">当前站点名称</param>
        /// <param name="onlyGetTransfer">默认false，标识是否只获取可换乘的站点，如果为true则只获取可换乘站点</param>
        /// <returns></returns>
        public static List<Station> GetClosestStation(string stationName, bool onlyGetTransfer = false)
        {
            var result = new List<Station>();
            var crosslines = AllSubwayLines.Where(x => x.Stations.Any(y => y.Name.IsSame(stationName))).ToList();
            foreach (var line in crosslines)
            {
                //站点在该线路的索引
                var cindex = GetIndexOnLine(stationName, line);
                var listTranInfo = (onlyGetTransfer ? line.GetTransStations() : line.Stations).Where(x => x.Index != cindex).Select(x =>
                   {
                       var o = new { Station = x, range = Math.Abs(cindex - x.Index) };
                       return o;
                   }).ToList();
                var listClosest = listTranInfo.Where(x => x.range == listTranInfo.Min(y => y.range)).ToList();
                if (listTranInfo.Count > 1 && listClosest.Count == 1)
                {
                    var listOther = listTranInfo.Where(x => x.Station.Index != listClosest.First().Station.Index).ToList();
                    var rang2 = listOther.Min(y => y.range);
                    var secondClosest = listOther.FirstOrDefault(x => cindex > listClosest.First().Station.Index
                        ? x.Station.Index > cindex &&
                          Math.Abs(x.Station.Index - cindex) == rang2
                        : x.Station.Index < cindex &&
                          Math.Abs(x.Station.Index - cindex) == rang2);
                    if (secondClosest != null)
                    {
                        listClosest.Add(secondClosest);
                    }
                }
                listClosest.ForEach(x => result.Add(x.Station));
            }
            return result;
        }

        /// <summary>
        /// 在同一条线路中，获取在该站点区间中到定点的最接近的站点：
        /// 即同一条线上的A、B、C三点，以A点为定点，B点和C点组成一个站点区间D，求出定点A到区间D中每个点的距离，返回和A距离最短的点
        /// </summary>
        /// <param name="fixStation">定点</param>
        /// <param name="items">站点区间</param>
        /// <returns></returns>
        public static Station GetClosestStation(this List<Station> items, string fixStation)
        {
            if (!items.Any()) return null;
            var line = GetLine(items.First().LineNo);//区间所在线路
            if (!line.Stations.Exists(x => x.Name.IsSame(fixStation))) return null;//定点不在线路上
            if (items.Count == 1) return items.First();
            var fixIndex = GetIndexOnLine(fixStation, line);//定点在线路上的索引
            var rcs =
                    items.Where(x => x.Name != fixStation)
                        .Select(x => new { Name = x.Name, rge = Math.Abs(fixIndex - x.Index) })
                        .ToList();
            var near = items.FirstOrDefault(x => x.Name == rcs.First(y => y.rge == rcs.Min(z => z.rge)).Name);
            return near;
        }

        /// <summary>
        /// 获取两条线路的交叉站点
        /// </summary>
        /// <param name="line1"></param>
        /// <param name="line2"></param>
        /// <returns></returns>
        public static List<Station> GetAcrossStations(this SubwayLine line1, SubwayLine line2)
        {
            var cross1 = line1.GetTransStations();
            var cross2 = line2.GetTransStations();
            var result = cross1.Intersect(cross2, new StationEquality()).ToList();
            return result;
        }

        /// <summary>
        /// 获取途经两个站点的交叉线路
        /// </summary>
        /// <param name="depStation"></param>
        /// <param name="destStation"></param>
        /// <returns></returns>
        public static List<SubwayLine> GetAcrossLines(string depStation, string destStation)
        {
            var afterDepLines = GetAcrossLines(depStation);
            var afterDestLines = GetAcrossLines(destStation);
            if (IsSameLine(depStation, destStation))//始发站和到达站同一条线路
            {
                return afterDepLines.Where(x => afterDestLines.Select(y => y.No).Contains(x.No)).ToList();
            }
            else
            {
                //不同线路，寻找共同交叉线
                var depTranStations = afterDepLines.Select(x => x.GetTransStations()).ToList();
                var destTranStations = afterDestLines.Select(x => x.GetTransStations()).ToList();
                var acrossStations = destTranStations.Where(x => depTranStations.Exists(y => y.Intersect(x, new StationEquality()).Any())).ToList();
                var acrossLines = acrossStations.Select(x => GetLine(x.First().LineNo)).ToList();
                return acrossLines;
            }
        }

        /// <summary>
        /// 获取经过始发站和到达站的线路中共同穿过的线路
        /// </summary>
        /// <param name="depStation"></param>
        /// <param name="destStation"></param>
        /// <returns></returns>
        public static List<SubwayLine> GetCommonLines(string depStation, string destStation)
        {
            var result = new List<SubwayLine>();
            var afterDepLines = GetAcrossLines(depStation);
            var afterDestLines = GetAcrossLines(destStation);
            //前置条件为两条线路不相交
            if (!IsSameLine(depStation, destStation) && GetAcrossLines(depStation, destStation).Count == 0)
            {
                var trans1 = afterDepLines.First().Stations.Where(x => x.CanTransfer).ToList();
                var trans2 = afterDestLines.First().Stations.Where(x => x.CanTransfer).ToList();
                var trans3 = new List<Station>();
                var expets = trans1.Join(trans2, x => x.TransferNo, y => y.TransferNo, (x, y) => x).ToList();
                expets.ForEach(x => result.Add(GetLine(x.TransferNo)));
            }
            var listDepTrans = new List<Station>();
            var listDestTrans = new List<Station>();
            afterDepLines.ForEach(x => listDepTrans.AddRange(x.GetTransStations().Where(y => !y.Name.IsSame(depStation))));
            afterDestLines.ForEach(x => listDestTrans.AddRange(x.GetTransStations().Where(y => !y.Name.IsSame(destStation))));
            var intersta = (from depTran in listDepTrans from destTran in listDestTrans where depTran.TransferNo.Split(',').Intersect(destTran.TransferNo.Split(',')).Any() select depTran).ToList();
            var gyline = intersta.GroupBy(x => x.TransferNo).Select(x => x.Key).ToList();
            gyline.ForEach(x =>
            {
                var nos = x.Split(',');
                foreach (var no in nos)
                {
                    if (result.Exists(y => y.No.IsSame(no))) continue;
                    result.Add(GetLine(no));
                }
            });
            return result;
        }

        /// <summary>
        /// 判断此站点是否换乘站
        /// </summary>
        /// <param name="stationName"></param>
        /// <returns></returns>
        public static bool IsTransferStation(string stationName)
        {
            return GetAcrossLines(stationName).First().Stations.Exists(x => x.Name.IsSame(stationName) && x.CanTransfer);
        }

        /// <summary>
        /// 判断两条地铁线路是否相交
        /// </summary>
        /// <param name="line1"></param>
        /// <param name="line2"></param>
        /// <returns></returns>
        public static bool IsIntersect(this SubwayLine line1, SubwayLine line2)
        {
            return GetAcrossStations(line1, line2).Count > 0;
        }

        /// <summary>
        /// 判断两个站点是否在同一条线路
        /// </summary>
        /// <param name="depStation"></param>
        /// <param name="destStation"></param>
        /// <returns></returns>
        public static bool IsSameLine(string depStation, string destStation)
        {
            return GetAcrossLines(depStation).Exists(x => GetAcrossLines(destStation).Select(y => y.No).Contains(x.No));
        }

        /// <summary>
        /// 获取在集合中某一个索引区间内的数据，传入的索引会自动判断是起始位或结束位
        /// </summary>
        /// <param name="source"></param>
        /// <param name="index1">索引1</param>
        /// <param name="index2">索引2</param>
        /// <returns></returns>
        public static List<Station> Between(this IEnumerable<Station> source, int index1, int index2)
        {
            if (source == null) return null;
            var line = GetLine(source.First().LineNo);
            var start = index1 > index2 ? index2 : index1;
            var end = index1 > index2 ? index1 : index2;
            if (!line.IsRound || (end - start) <= line.Stations.Count / 2)
                return source.Where((x, n) => n >= start && n <= end).ToList();//非环形线路直接获取距离
            {
                //环形线路需要反向求距离
                var r1 = line.Stations.Where((x, n) => n >= end && n <= line.Stations.Count).ToList();
                var r2 = line.Stations.Where((x, n) => n <= start).ToList();
                r1.AddRange(r2);
                r1.Reverse();
                return r1;
            }
        }

        public static void Loop(this List<Station> nears, string dep, string dest, ref List<string> route, ref int times, ref bool isfind)
        {
            var route2 = route;
            while (!nears.Exists(x => x.Name == dest))
            {
                foreach (var near in nears)
                {
                    times += 1;
                    route.Add(near.Name);
                    var nns = GetClosestStation(near.Name).Where(x => x.Name != dep && !route2.Exists(y => y == x.Name)).ToList();
                    Loop(nns, dep, dest, ref route, ref times, ref isfind);
                    if (isfind) break;
                }
                if (isfind) break;
            }
            isfind = true;

        }

        public static List<Station> LoopLine(string dep, string dest)
        {
            var routes = new List<string>();
            var times = 0;
            var isfind = false;
            var nears = GetClosestStation(dep);
            Loop(nears, dep, dest, ref routes, ref times, ref isfind);
            return null;
        }

        /// <summary>
        /// 获取地铁乘车信息
        /// </summary>
        /// <param name="depStation">出发站</param>
        /// <param name="destStation">到达站</param>
        /// <param name="city">所在城市</param>
        /// <returns>返回各种换乘方案</returns>
        public static List<QueryResult> GetRideSubwayInfo(string depStation, string destStation, CityEnum city)
        {
            InitSubwayLine(city);
            //LoopLine(depStation, destStation);
            if (string.IsNullOrWhiteSpace(depStation) || string.IsNullOrWhiteSpace(destStation)
                || !AllSubwayLines.Exists(x => x.Stations.Exists(y => y.Name.Equals(depStation)))
                || !AllSubwayLines.Exists(x => x.Stations.Exists(y => y.Name.Equals(destStation))))
                return null;//出发站或到达站在线路上不存在！

            //各种换乘提示
            //同一条线路
            var msg_oneline = "在{0}【{1}】上车，经过{2}站到达目的站【{3}】。\r\n具体线路为：\r\n(出发){4}(到达)\r\n总搭乘站点数：{5}\r\n";
            //换乘1次
            var msg_transOnce = "在{0}【{1}】上车，经过{2}站在【{3}】下车，换乘{4}，经过{5}站到达目的站【{6}】。\r\n具体线路为：\r\n(出发){7}(此处换乘{4})-->{8}(到达)\r\n总搭乘站点数：{9}\r\n";
            //换乘2次
            var msg_transTwice = "在{0}【{1}】上车，经过{2}站在【{3}】下车，换乘{4}，经过{5}站在【{6}】下车，换乘{7}，经过{8}站到达目的站【{9}】。\r\n具体线路为：\r\n(出发){10}(此处换乘{4})-->{11}(此处换乘{7})-->{12}(到达)\r\n总搭乘站点数：{13}\r\n";
            //换乘3次
            var msg_transThreetimes = "在{0}【{1}】上车，经过{2}站在【{3}】下车，换乘{4}，经过{5}站在【{6}】下车，换乘{7}，经过{8}站在【{9}】下车，换乘{10}，经过{11}站到达目的站【{12}】。"
                + "\r\n具体线路为：\r\n(出发){13}(此处换乘{4})-->{14}(此处换乘{7})-->{15}(此处换乘{10})-->{16}(到达)\r\n总搭乘站点数：{17}\r\n";
            //换乘4次
            var msg_transFourtimes = "在{0}【{1}】上车，经过{2}站在【{3}】下车，换乘{4}，经过{5}站在【{6}】下车，换乘{7}，经过{8}站在【{9}】下车，换乘{10}，经过{11}站在【{12}】下车，换乘{13}，经过{14}站到达目的站【{15}】。"
                + "\r\n具体线路为：\r\n(出发){16}(此处换乘{4})-->{17}(此处换乘{7})-->{18}(此处换乘{10})-->{19}(此处换乘{13})-->{20}(到达)\r\n总搭乘站点数：{21}\r\n";

            //保存各种换乘方案
            var result = new List<QueryResult>();
            //第一步：先查找始发站和到达站在哪一条线路
            var afterDepLines = GetAcrossLines(depStation);
            var afterDestLines = GetAcrossLines(destStation);
            //根据同一条线和不同线路展开分析
            if (IsSameLine(depStation, destStation))
            {
                #region 同一条线路
                var commLines = afterDepLines.Where(x => afterDestLines.Select(y => y.No).Contains(x.No)).ToList();
                //判断线路是否相同，相同直接计算站点距离
                var depIndex = GetIndexOnLine(depStation, commLines.First());
                var destIndex = GetIndexOnLine(destStation, commLines.First());
                var crossStations = commLines.First().Stations.Between(depIndex, destIndex).Select(x => x.Name).ToList();
                var range = crossStations.Count - 1;
                if (depIndex > destIndex) crossStations.Reverse();
                var rs = msg_oneline.FormatTo(commLines.First().ToString(), depStation, range, destStation,
                         crossStations.ToJoinString(), range);
                result.Add(new QueryResult() { Description = rs, Range = range });
                #endregion
            }
            else
            {
                #region 不同线路
                if (!IsTransferStation(depStation) && !IsTransferStation(destStation))//如果始发站和终点站都不是换乘站，则表示始发站和到达站都是只有一条线路通过
                {
                    if (afterDepLines.First().IsIntersect(afterDestLines.First()))
                    {
                        #region 如果两条线路交叉，一定有换乘站点
                        var clist = GetAcrossStations(afterDepLines.First(), afterDestLines.First()).Select(x => x.Name).ToList();
                        var i = GetIndexOnLine(depStation, afterDepLines.First());
                        var j = GetIndexOnLine(clist.First(), afterDepLines.First());
                        var k = GetIndexOnLine(destStation, afterDestLines.First());
                        var l = GetIndexOnLine(clist.First(), afterDestLines.First());
                        var coss1 = afterDepLines.First().Stations.Between(i, j).Select(x => x.Name).ToList();
                        var coss2 = afterDestLines.First().Stations.Between(k, l).Select(x => x.Name).ToList();
                        if (i > j) coss1.Reverse();
                        if (k < l) coss2.Reverse();
                        var rang1 = coss1.Count - 1;
                        var rang2 = coss2.Count - 1;
                        var h = rang1 + rang2; //站点数
                        var rs = msg_transOnce.FormatTo(afterDepLines.First().ToString(), depStation, rang1, clist.First(),
                            afterDestLines.First().ToString(), rang2, destStation,
                            coss1.ToJoinString(), coss2.Where(x => x != clist.First()).ToJoinString(), h);
                        result.Add(new QueryResult()
                        {
                            Description = rs,
                            Range = h,
                            TransferStations = new List<string>() { clist.First() },
                            TransferTimes = 1
                        });
                        #endregion
                    }
                    else
                    {
                        #region 不交叉，需要通过第三条线路换乘，即多次换乘
                        var depSta = GetStation(depStation);
                        var destSta = GetStation(destStation);
                        //找出两条线路的可换乘站点，找出可换乘相同线路的站点
                        var trans1 = afterDepLines.First().GetTransStations();
                        var trans2 = afterDestLines.First().GetTransStations();
                        var trans3 = new List<Station>();
                        var trans4 = new List<Station>();
                        var expets = trans1.Join(trans2, x => x.TransferNo, y => y.TransferNo, (x, y) =>
                        {
                            trans3.Add(x);
                            trans4.Add(y);
                            return x.Name + "---" + y.Name;
                        }).ToList();
                        if (expets.Any())
                        {
                            #region 两次换乘
                            //trans3.Count和trans4.Count必定相等
                            //计算最短距离，列出所有换乘方案
                            for (var i = 0; i < trans3.Count; i++)
                            {
                                var tranLine = GetLine(trans3[i].TransferNo);
                                //获取这两个站点在此线路的索引                   
                                var ix1 = depSta.Index;
                                var ix2 = destSta.Index;
                                var iix1 = GetIndexOnLine(trans3[i].Name, depSta.LineNo);
                                var iix2 = GetIndexOnLine(trans4[i].Name, destSta.LineNo);
                                var tx1 = GetIndexOnLine(trans3[i].Name, tranLine);
                                var tx2 = GetIndexOnLine(trans4[i].Name, tranLine);

                                var depRange = afterDepLines.First().Stations.Between(ix1, iix1).Select(x => x.Name).ToList();
                                var destRange = afterDestLines.First().Stations.Between(ix2, iix2).Select(x => x.Name).ToList();
                                var transRange = tranLine.Stations.Between(tx1, tx2).Select(x => x.Name).ToList();
                                if (ix1 > iix1) depRange.Reverse();
                                if (ix2 < iix2) destRange.Reverse();
                                if (tx1 > tx2) transRange.Reverse();
                                var r1 = depRange.Count - 1;
                                var r2 = destRange.Count - 1;
                                var r3 = transRange.Count - 1;
                                var r = r1 + r2 + r3;
                                var rs = msg_transTwice.FormatTo(afterDepLines.First().ToString(), depStation, r1,
                                    trans3[i].Name,
                                    tranLine.ToString(), r3, trans4[i].Name, afterDestLines.First().ToString(), r2,
                                    destStation, depRange.ToJoinString(),
                                        transRange.Where(x => !x.IsSame(trans3[i].Name)).ToJoinString(),
                                     destRange.Where(x => x != trans4[i].Name).ToJoinString(), r);
                                result.Add(new QueryResult()
                                {
                                    Description = rs,
                                    Range = r,
                                    TransferTimes = 2,
                                    TransferStations = new List<string>() { trans3[i].Name, trans4[i].Name }
                                });
                            }
                            #endregion
                        }
                        #region 查找3次以上换乘的可能结果，寻求最短距离
                        var trlines1 = afterDepLines.First().TransferLines.Select(GetLine).ToList();
                        var trlines2 = afterDestLines.First().TransferLines.Select(GetLine).ToList();
                        var destss = new List<Station>();

                        #region 换乘3次
                        foreach (var depline in trlines1)
                        {
                            foreach (var destline in trlines2)
                            {
                                var ss = destline.GetAcrossStations(depline);
                                if (!ss.Any()) continue; //3次换乘
                                var slist1 = afterDepLines.First().GetAcrossStations(depline);
                                if (!slist1.Any()) continue;
                                var s1 = slist1.GetClosestStation(depSta.Name);
                                var s1_ix1 = depSta.Index;
                                var s1_ix2 = s1.Index;
                                var s1_range =
                                    afterDepLines.First()
                                        .Stations.Between(s1_ix1, s1_ix2)
                                        .Select(x => x.Name)
                                        .ToList();
                                var s1_h = s1_range.Count - 1;
                                if (s1_ix1 > s1_ix2) s1_range.Reverse();

                                var s2_ix1 = GetIndexOnLine(s1.Name, depline);
                                var s2_ix2 = GetIndexOnLine(ss.First().Name, depline);
                                var s2_range = depline.Stations.Between(s2_ix1, s2_ix2).Select(x => x.Name).ToList();
                                var s2_h = s2_range.Count - 1;
                                if (s2_ix1 > s2_ix2) s2_range.Reverse();

                                var slist3 = destline.GetAcrossStations(afterDestLines.First());
                                if (!slist3.Any()) continue;
                                var s3 = slist3.GetClosestStation(ss.First().Name);
                                var s3_ix1 = s3.Index;
                                var s3_ix2 = ss.First().Index;
                                var s3_range = destline.Stations.Between(s3_ix1, s3_ix2).Select(x => x.Name).ToList();
                                var s3_h = s3_range.Count - 1;
                                if (s3_ix1 < s3_ix2) s3_range.Reverse();

                                var s4_ix1 = GetIndexOnLine(s3.Name, afterDestLines.First());
                                var s4_ix2 = destSta.Index;
                                var s4_range =
                                    afterDestLines.First()
                                        .Stations.Between(s4_ix1, s4_ix2)
                                        .Select(x => x.Name)
                                        .ToList();
                                var s4_h = s4_range.Count - 1;
                                if (s4_ix1 > s4_ix2) s4_range.Reverse();

                                if (s1_h == 0 || s2_h == 0 || s3_h == 0 || s4_h == 0) continue;
                                var h = s1_h + s2_h + s3_h + s4_h;

                                var rs = msg_transThreetimes.FormatTo(afterDepLines.First().ToString(), depStation,
                                    s1_h, s1.Name,
                                    depline.ToString(), s2_h, ss.First().Name,
                                    GetLine(ss.First().LineNo).ToString(), s3_h, s3.Name,
                                    afterDestLines.First().ToString(), s4_h, destStation, s1_range.ToJoinString(),
                                    s2_range.Where(x => x != s1.Name).ToJoinString(),
                                    s3_range.Where(x => x != ss.First().Name).ToJoinString(),
                                    s4_range.Where(x => x != s3.Name).ToJoinString(), h);
                                result.Add(new QueryResult()
                                {
                                    Description = rs,
                                    Range = h,
                                    TransferTimes = 3,
                                    TransferStations =
                                        new List<string>()
                                        {
                                                        s1.Name,
                                                        ss.First().Name,
                                                        s3.Name
                                        }
                                });
                                destss.AddRange(ss);
                            }
                        }
                        #endregion

                        if (!destss.Any()) //换乘4次
                        {
                            #region 换乘4次
                            foreach (var depline in trlines1)
                            {
                                foreach (var destline in trlines2)
                                {
                                    var deptrlines =
                                        depline.TransferLines.Where(x => x != afterDepLines.First().No)
                                            .Select(GetLine)
                                            .ToList();
                                    foreach (var line in deptrlines)
                                    {
                                        var s1 = line.GetAcrossStations(destline);
                                        if (!s1.Any()) continue; //4次换乘
                                        var trlist1 = afterDepLines.First().GetAcrossStations(depline);
                                        if (!trlist1.Any()) continue;
                                        var tr1 = trlist1.GetClosestStation(depSta.Name);
                                        var s1_ix1 = depSta.Index;
                                        var s1_ix2 = tr1.Index;
                                        var s1_range =
                                            afterDepLines.First()
                                                .Stations.Between(s1_ix1, s1_ix2)
                                                .Select(x => x.Name)
                                                .ToList();
                                        var h1 = s1_range.Count - 1;
                                        if (s1_ix1 > s1_ix2) s1_range.Reverse();

                                        var trlist2 = GetLine(tr1.TransferNo).GetAcrossStations(line);
                                        if (!trlist2.Any()) continue;
                                        var tr2 = trlist2.GetClosestStation(tr1.Name);
                                        var s2_ix1 = GetIndexOnLine(tr1.Name, depline);
                                        var s2_ix2 = tr2.Index;
                                        var s2_range =
                                            depline.Stations.Between(s2_ix1, s2_ix2)
                                                .Select(x => x.Name)
                                                .ToList();
                                        var h2 = s2_range.Count - 1;
                                        if (s2_ix1 > s2_ix2) s2_range.Reverse();

                                        var s3_ix1 = GetIndexOnLine(tr2.Name, line);
                                        var s3_ix2 = s1.First().Index;
                                        var s3_range =
                                            line.Stations.Between(s3_ix1, s3_ix2)
                                                .Select(x => x.Name)
                                                .ToList();
                                        var h3 = s3_range.Count - 1;
                                        if (s3_ix1 > s3_ix2) s3_range.Reverse();

                                        var trlist3 = destline.GetAcrossStations(afterDestLines.First());
                                        if (!trlist3.Any()) continue;
                                        var tr3 = trlist3.GetClosestStation(s1.First().Name);
                                        var s4_ix1 = GetIndexOnLine(s1.First().Name, destline);
                                        var s4_ix2 = tr3.Index;
                                        var s4_range =
                                            destline.Stations.Between(s4_ix1, s4_ix2)
                                                .Select(x => x.Name)
                                                .ToList();
                                        var h4 = s4_range.Count - 1;
                                        if (s4_ix1 > s4_ix2) s4_range.Reverse();

                                        var s5_ix1 = GetIndexOnLine(tr3.Name, afterDestLines.First());
                                        var s5_ix2 = destSta.Index;
                                        var s5_range =
                                            afterDestLines.First()
                                                .Stations.Between(s5_ix1, s5_ix2)
                                                .Select(x => x.Name)
                                                .ToList();
                                        var h5 = s5_range.Count - 1;
                                        if (s5_ix1 > s5_ix2) s5_range.Reverse();
                                        var h = h1 + h2 + h3 + h4 + h5;
                                        var rs =
                                            msg_transFourtimes.FormatTo(afterDepLines.First().ToString(),
                                                depStation, h1, tr1.Name,
                                                depline.ToString(), h2, tr2.Name,
                                                line.ToString(), h3, s1.First().Name,
                                                destline.ToString(), h4, tr3.Name,
                                               afterDestLines.First().ToString(), h5, destStation,
                                                s1_range.ToJoinString(),
                                                s2_range.Where(x => x != tr1.Name).ToJoinString(),
                                                s3_range.Where(x => x != tr2.Name).ToJoinString(),
                                                s4_range.Where(x => x != tr2.Name && x != s1.First().Name).ToJoinString(),
                                                s5_range.Where(x => x != tr3.Name).ToJoinString(), h);
                                        result.Add(new QueryResult()
                                        {
                                            Description = rs,
                                            Range = h,
                                            TransferTimes = 4,
                                            TransferStations =
                                                new List<string>()
                                                {
                                                            tr1.Name,
                                                            tr2.Name,
                                                            s1.First().Name,
                                                            tr3.Name
                                                }
                                        });
                                        destss.AddRange(s1);
                                    }
                                }
                            }
                            #endregion
                        }
                        if (!destss.Any())//换乘4次以上
                        {

                        }
                        #endregion
                        #endregion
                    }
                }
                else //始发站和到达站有其中一个是换乘站
                {
                    //找出到达站经过的路线和始发站所在路线的交叉线路
                    var crossLines = GetAcrossLines(depStation, destStation);
                    //分三种情况：1、始发站不是换乘站而到达站是换乘站；2、始发站是换乘站而到达站不是换乘站；3、始发站和到达站都是换乘站，根据情况展开分析
                    if (!IsTransferStation(depStation) && IsTransferStation(destStation))
                    {
                        #region 情况1：始发站不是换乘站而到达站是换乘站
                        if (crossLines.Count > 0) //依赖交叉线
                        {
                            var listTrans = new List<Station>();
                            foreach (var line in crossLines)
                            {
                                //找出每条交叉线换乘到始发站线路的所有换乘站
                                var ss = line.GetTransStations()
                                        .Where(x => x.TransferNo.IsSame(afterDepLines.First().No))
                                        .ToList();
                                listTrans.AddRange(ss);
                            }
                            var depIx = GetIndexOnLine(depStation, afterDepLines.First());
                            var tranStas =
                                listTrans.Select(
                                        s => new { sta = s, ix = GetIndexOnLine(s.Name, afterDepLines.First()) })
                                    .ToList();
                            foreach (var sta in tranStas)
                            {
                                var destIx = GetIndexOnLine(destStation, sta.sta.LineNo);
                                var tranIx = GetIndexOnLine(sta.sta.Name, sta.sta.LineNo);
                                var coss1 =
                                    afterDepLines.First()
                                        .Stations.Between(depIx, sta.ix)
                                        .Select(x => x.Name)
                                        .ToList();
                                var coss2 =
                                    GetLine(sta.sta.LineNo)
                                        .Stations.Between(destIx, tranIx)
                                        .Select(x => x.Name)
                                        .ToList();
                                var rang1 = coss1.Count - 1;
                                var rang2 = coss2.Count - 1;
                                var h = rang1 + rang2; //站点数
                                if (depIx > sta.ix) coss1.Reverse();
                                if (destIx < tranIx) coss2.Reverse();

                                var rs = msg_transOnce.FormatTo(afterDepLines.First().ToString(), depStation, rang1,
                                    sta.sta.Name,
                                    GetLine(sta.sta.LineNo).ToString(), rang2, destStation,
                                    coss1.ToJoinString(), coss2.Where(x => x != sta.sta.Name).ToJoinString(), h);
                                result.Add(new QueryResult()
                                {
                                    Description = rs,
                                    Range = h,
                                    TransferTimes = 1,
                                    TransferStations = new List<string>() { sta.sta.Name }
                                });
                            }
                        }
                        //查找其他换乘可能
                        var depSta = GetStation(depStation);
                        var trlinesDep = afterDepLines.First().TransferLines.Select(GetLine).ToList();
                        foreach (var depline in afterDestLines)
                        {
                            var trlineItems = depline.TransferLines.Select(GetLine).ToList();
                            foreach (var iline in trlineItems)
                            {
                                foreach (var destline in trlinesDep)
                                {
                                    var ss = destline.GetAcrossStations(iline);
                                    if (!ss.Any()) continue; //3次换乘
                                    var slist1 = afterDepLines.First().GetAcrossStations(destline);
                                    if (!slist1.Any()) continue;
                                    var s1 = slist1.GetClosestStation(depStation);
                                    var s1_ix1 = depSta.Index;
                                    var s1_ix2 = s1.Index;

                                    var s1_range =
                                        afterDepLines.First()
                                            .Stations.Between(s1_ix1, s1_ix2)
                                            .Select(x => x.Name)
                                            .ToList();
                                    var s1_h = s1_range.Count - 1;
                                    if (s1_ix1 > s1_ix2) s1_range.Reverse();

                                    var s2 = ss.GetClosestStation(s1.Name);
                                    var s2_ix1 = GetIndexOnLine(s1.Name, destline);
                                    var s2_ix2 = GetIndexOnLine(s2.Name, destline);
                                    var s2_range = destline.Stations.Between(s2_ix1, s2_ix2).Select(x => x.Name).ToList();
                                    var s2_h = s2_range.Count - 1;
                                    if (s2_ix1 > s2_ix2) s2_range.Reverse();

                                    var slist3 = iline.GetAcrossStations(depline);
                                    if (!slist3.Any()) continue;
                                    var s3 = slist3.GetClosestStation(s2.Name);
                                    var s3_ix1 = s3.Index;
                                    var s3_ix2 = GetIndexOnLine(s2.Name, iline);
                                    var s3_range = iline.Stations.Between(s3_ix1, s3_ix2).Select(x => x.Name).ToList();
                                    var s3_h = s3_range.Count - 1;
                                    if (s3_ix1 < s3_ix2) s3_range.Reverse();

                                    var s4_ix1 = GetIndexOnLine(s3.Name, depline);
                                    var s4_ix2 = GetIndexOnLine(destStation, depline);
                                    var s4_range = depline.Stations.Between(s4_ix1, s4_ix2)
                                        .Select(x => x.Name)
                                        .ToList();
                                    var s4_h = s4_range.Count - 1;
                                    if (s4_ix1 > s4_ix2) s4_range.Reverse();

                                    var h = s1_h + s2_h + s3_h + s4_h;
                                    if (s2_h == 0 || s3_h == 0 || s4_h == 0 || destline.No.IsSame(iline.No)) continue;
                                    var rs = msg_transThreetimes.FormatTo(afterDepLines.First().ToString(),
                                        depStation,
                                        s1_h, s1.Name,
                                        destline.ToString(), s2_h, s2.Name,
                                        iline.ToString(), s3_h, s3.Name,
                                        depline.ToString(), s4_h, destStation, s1_range.ToJoinString(),
                                        s2_range.Where(x => x != s1.Name).ToJoinString(),
                                        s3_range.Where(x => x != s2.Name).ToJoinString(),
                                        s4_range.Where(x => x != s3.Name).ToJoinString(), h);
                                    result.Add(new QueryResult()
                                    {
                                        Description = rs,
                                        Range = h,
                                        TransferTimes = 3,
                                        TransferStations =
                                            new List<string>()
                                            {
                                                    s1.Name,
                                                    s2.Name,
                                                    s3.Name
                                            }
                                    });
                                }
                            }
                        }
                        #endregion
                    }
                    if (IsTransferStation(depStation) && !IsTransferStation(destStation))
                    {
                        #region 情况2：始发站是换乘站而到达站不是换乘站
                        var transLines =
                            afterDepLines.Where(
                                    x =>
                                        x.Stations.Exists(
                                            y => y.CanTransfer && y.TransferNo.Contains(afterDestLines.First().No)))
                                .ToList();
                        if (transLines.Any())
                        {
                            var clist =
                                GetAcrossStations(transLines.First(), afterDestLines.First())
                                    .Select(x => x.Name)
                                    .ToList();
                            foreach (var c in clist)
                            {
                                var i = GetIndexOnLine(depStation, transLines.First());
                                var j = GetIndexOnLine(c, transLines.First());
                                var k = GetIndexOnLine(destStation, afterDestLines.First());
                                var l = GetIndexOnLine(c, afterDestLines.First());
                                var coss1 = transLines.First().Stations.Between(i, j).Select(x => x.Name).ToList();
                                var coss2 = afterDestLines.First().Stations.Between(k, l).Select(x => x.Name).ToList();
                                var rang1 = coss1.Count - 1;
                                var rang2 = coss2.Count - 1;
                                var h = rang1 + rang2; //站点数
                                if (i > j) coss1.Reverse();
                                if (k < l) coss2.Reverse();

                                var rs = msg_transOnce.FormatTo(transLines.First().ToString(), depStation, rang1,
                                    c,
                                    afterDestLines.First().ToString(), rang2, destStation,
                                    coss1.ToJoinString(), coss2.Where(x => x != c).ToJoinString(), h);
                                result.Add(new QueryResult()
                                {
                                    Description = rs,
                                    Range = h,
                                    TransferTimes = 1,
                                    TransferStations = new List<string>() { c }
                                });
                            }
                        }
                        //寻找其他换乘可能
                        var destSta = GetStation(destStation);
                        var trlinesDest = afterDestLines.First().TransferLines.Select(GetLine).ToList();
                        foreach (var depline in afterDepLines)
                        {
                            var trlineItems = depline.TransferLines.Select(GetLine).ToList();
                            foreach (var iline in trlineItems)
                            {
                                foreach (var destline in trlinesDest)
                                {
                                    var ss = iline.GetAcrossStations(destline);
                                    if (!ss.Any()) continue; //3次换乘
                                    var slist1 = depline.GetAcrossStations(iline);
                                    if (!slist1.Any()) continue;
                                    var s1 = slist1.GetClosestStation(depStation);
                                    var s1_ix1 = GetIndexOnLine(depStation, depline);
                                    var s1_ix2 = s1.Index;
                                    var s1_range =
                                        depline.Stations.Between(s1_ix1, s1_ix2)
                                            .Select(x => x.Name)
                                            .ToList();
                                    var s1_h = s1_range.Count - 1;
                                    if (s1_ix1 > s1_ix2) s1_range.Reverse();

                                    var s2 = ss.GetClosestStation(s1.Name);
                                    var s2_ix1 = GetIndexOnLine(s1.Name, iline);
                                    var s2_ix2 = GetIndexOnLine(s2.Name, iline);
                                    var s2_range = iline.Stations.Between(s2_ix1, s2_ix2).Select(x => x.Name).ToList();
                                    var s2_h = s2_range.Count - 1;
                                    if (s2_ix1 > s2_ix2) s2_range.Reverse();

                                    var slist3 = destline.GetAcrossStations(afterDestLines.First());
                                    if (!slist3.Any()) continue;
                                    var s3 = slist3.GetClosestStation(ss.First().Name);
                                    var s3_ix1 = s3.Index;
                                    var s3_ix2 = GetIndexOnLine(s2.Name, destline);
                                    var s3_range = destline.Stations.Between(s3_ix1, s3_ix2).Select(x => x.Name).ToList();
                                    var s3_h = s3_range.Count - 1;
                                    if (s3_ix1 < s3_ix2) s3_range.Reverse();

                                    var s4_ix1 = GetIndexOnLine(s3.Name, afterDestLines.First());
                                    var s4_ix2 = destSta.Index;
                                    var s4_range =
                                        afterDestLines.First()
                                            .Stations.Between(s4_ix1, s4_ix2)
                                            .Select(x => x.Name)
                                            .ToList();
                                    var s4_h = s4_range.Count - 1;
                                    if (s4_ix1 > s4_ix2) s4_range.Reverse();

                                    var h = s1_h + s2_h + s3_h + s4_h;
                                    if (s1_h == 0 || s2_h == 0 || s3_h == 0 || iline.No.IsSame(destline.No)) continue;
                                    var rs = msg_transThreetimes.FormatTo(depline.ToString(), depStation,
                                        s1_h, s1.Name,
                                        iline.ToString(), s2_h, s2.Name,
                                        destline.ToString(), s3_h, s3.Name,
                                        afterDestLines.First().ToString(), s4_h, destStation,
                                        s1_range.ToJoinString(),
                                        s2_range.Where(x => x != s1.Name).ToJoinString(),
                                        s3_range.Where(x => x != s2.Name).ToJoinString(),
                                        s4_range.Where(x => x != s3.Name).ToJoinString(), h);
                                    result.Add(new QueryResult()
                                    {
                                        Description = rs,
                                        Range = h,
                                        TransferTimes = 3,
                                        TransferStations =
                                            new List<string>()
                                            {
                                                    s1.Name,
                                                    s2.Name,
                                                    s3.Name
                                            }
                                    });
                                }
                            }
                        }
                        #endregion
                    }
                    if (IsTransferStation(depStation) && IsTransferStation(destStation))
                    {
                        #region 情况3：始发站和到达站都是换乘站
                        if (crossLines.Count > 0) //依赖交叉线
                        {
                            var transStations = GetClosestStation(depStation, true);
                            if (
                                !transStations.Exists(
                                    x =>
                                        crossLines.Exists(y => y.Stations.Exists(z => x.TransferNo.Split(',').Intersect(z.LineNo.Split(',')).Any()))))
                            {
                                transStations = new List<Station>();
                                afterDepLines.ForEach(x =>
                                {
                                    var ctrans = x.GetTransStations();
                                    var ctrans2 =
                                        ctrans.Where(
                                                y =>
                                                    crossLines.Exists(
                                                        z => z.Stations.Exists(zz => y.TransferNo.Split(',').Intersect(zz.LineNo.Split(',')).Any())))
                                            .ToList();
                                    transStations.AddRange(ctrans2);
                                });
                            }
                            var transLine =
                                afterDestLines.Where(
                                        x =>
                                            x.Stations.Exists(y => transStations.Exists(z => z.Name.IsSame(y.Name))))
                                    .ToList();
                            var intersStas =
                                transStations.Where(
                                        x =>
                                            transLine.Exists(
                                                y =>
                                                    y.Stations.Exists(
                                                        z => z.Name.IsSame(x.Name) && x.TransferNo.Split(',').Intersect(z.LineNo.Split(',')).Any())))
                                    .ToList();
                            foreach (var line in transLine)
                            {
                                //分别获取换乘站在换乘线上的索引
                                foreach (var t in intersStas)
                                {
                                    var ix = GetIndexOnLine(destStation, line); //目的站在换乘线上的索引
                                    var iix = GetIndexOnLine(t.Name, line); //换乘站在换乘线上的索引
                                    if (iix == -1) continue;
                                    var ix2 = GetIndexOnLine(depStation, t.LineNo); //始发站在换乘站所在线路上的索引
                                    var iix2 = GetIndexOnLine(t.Name, t.LineNo); //换乘站在始发站所在线路上的索引

                                    var ixRange = line.Stations.Between(ix, iix).Select(x => x.Name).ToList();
                                    var ixRange2 = GetLine(t.LineNo).Stations.Between(ix2, iix2).Select(x => x.Name).ToList();
                                    var ixh = ixRange.Count - 1;
                                    var ixh2 = ixRange2.Count - 1;
                                    var h = ixh + ixh2;
                                    if (ix < iix) ixRange.Reverse();
                                    if (ix2 > iix2) ixRange2.Reverse();
                                    var rs = msg_transOnce.FormatTo(GetLine(t.LineNo).ToString(), depStation, ixh2, t.Name,
                                        line.ToString(), ixh, destStation,
                                        ixRange2.ToJoinString(),
                                        ixRange.Where(x => !x.IsSame(t.Name)).ToJoinString(), h);
                                    result.Add(new QueryResult()
                                    {
                                        Description = rs,
                                        Range = h,
                                        TransferTimes = 1,
                                        TransferStations = new List<string>() { t.Name }
                                    });
                                }
                            }
                        }
                        #endregion
                    }
                }
                #endregion
            }

            //查找其他可能性
            #region 深度挖掘其他方案
            //找出经过始发站和到达站的线路中共同穿过的公共线路，寻找换乘方案
            var connLines = GetCommonLines(depStation, destStation);
            if (connLines.Count > 0)
            {
                var transDep = new List<Station>();
                var transDest = new List<Station>();
                foreach (var depLine in afterDepLines)
                {
                    //在经过始发站的线路中的站点中找到可换乘到公共线路的站点
                    var trans = depLine.GetTransStations()
                            .Where(x => x.Name != depStation && x.Name != destStation && connLines.Exists(y => x.TransferNo.Contains(y.No)))
                            .ToList();
                    transDep.AddRange(trans);
                }
                foreach (var destLine in afterDestLines)
                {
                    //在经过到达站的线路中的站点中找到可换乘到公共线路的站点
                    var trans = destLine.GetTransStations()
                            .Where(x => x.Name != depStation && x.Name != destStation && connLines.Exists(y => x.TransferNo.Contains(y.No)))
                            .ToList();
                    transDest.AddRange(trans);
                }
                foreach (var d1 in transDep)
                {
                    foreach (var d2 in transDest)
                    {
                        //找出交叉站点，即可换乘同一条公共线路的站点
                        var inters = d1.TransferNo.Split(',').Intersect(d2.TransferNo.Split(',')).ToList();
                        if (!inters.Any() || d1.Name.IsSame(d2.Name)) continue;
                        var tranLine = GetLine(inters.First());
                        var depLine = GetLine(d1.LineNo);
                        var destLine = GetLine(d2.LineNo);
                        var ix1 = GetIndexOnLine(depStation, depLine);
                        var ix2 = GetIndexOnLine(d1.Name, depLine);
                        var iix1 = GetIndexOnLine(d1.Name, tranLine);
                        var iix2 = GetIndexOnLine(d2.Name, tranLine);
                        var iiix1 = GetIndexOnLine(d2.Name, destLine);
                        var iiix2 = GetIndexOnLine(destStation, destLine);

                        var depRange = depLine.Stations.Between(ix1, ix2).Select(x => x.Name).ToList();
                        var transRange = tranLine.Stations.Between(iix1, iix2).Select(x => x.Name).ToList();
                        var destRange = destLine.Stations.Between(iiix1, iiix2).Select(x => x.Name).ToList();
                        var r1 = depRange.Count - 1;
                        var r2 = transRange.Count - 1;
                        var r3 = destRange.Count - 1;
                        var r = r1 + r2 + r3;
                        if (ix1 > ix2) depRange.Reverse();
                        if (iix1 > iix2) transRange.Reverse();
                        if (iiix1 > iiix2) destRange.Reverse();
                        string rs;
                        if (r1 > 0 && r2 > 0 && r3 > 0)
                        {
                            rs = msg_transTwice.FormatTo(depLine.ToString(), depStation, r1, d1.Name, tranLine.ToString(), r2,
                                    d2.Name, destLine.ToString(), r3, destStation, depRange.ToJoinString(),
                                      transRange.Where(x => !x.IsSame(d1.Name)).ToJoinString(),
                                    destRange.Where(x => !x.IsSame(d1.Name) && !x.IsSame(d2.Name)).ToJoinString(), r);
                            result.Add(new QueryResult()
                            {
                                Description = rs,
                                Range = r,
                                TransferTimes = 2,
                                TransferStations = new List<string>() { d1.Name, d2.Name }
                            });
                        }
                        else if (r1 > 0 && r2 == 0 && r3 > 0)
                        {
                            rs = msg_transOnce.FormatTo(GetLine(inters.First()).ToString(), depStation, r1, d2.Name,
                                  destLine.ToString(), r3, destStation,
                                  depRange.ToJoinString(),
                                 destRange.Where(x => !x.IsSame(d2.Name)).ToJoinString(), r);
                            result.Add(new QueryResult()
                            {
                                Description = rs,
                                Range = r,
                                TransferTimes = 1,
                                TransferStations = new List<string>() { d2.Name }
                            });
                        }
                        else
                        {
                            rs = msg_transOnce.FormatTo(depLine.ToString(), depStation, r1, d1.Name, tranLine.ToString(), r2,
                                    destStation, depRange.ToJoinString(),
                                    transRange.Where(x => !x.IsSame(d1.Name)).ToJoinString(), r);
                            result.Add(new QueryResult()
                            {
                                Description = rs,
                                Range = r,
                                TransferTimes = 1,
                                TransferStations = new List<string>() { d1.Name }
                            });
                        }
                    }
                }
            }
            #endregion

            //重新组织数据
            result.ForEach(x =>
            {
                var desc = x.Description.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                x.Suggestion = desc[0];
                x.Route = desc[2];
            });
            //去除重复方案，保留一个
            var gyResult = result.GroupBy(x => x.Route).Select(x => x.First()).ToList();
            //移除逗逼方案，例如：A-B-A-C
            gyResult.RemoveAll(x => x.Route.Split(new string[] { depStation }, StringSplitOptions.RemoveEmptyEntries).Length > 2
            || x.Route.Split(new string[] { destStation }, StringSplitOptions.RemoveEmptyEntries).Length > 2);
            return gyResult;
        }
    }

    /// <summary>
    /// 城市枚举
    /// </summary>
    public enum CityEnum
    {
        /// <summary>
        /// 广州
        /// </summary>
        GuangZhou,
        /// <summary>
        /// 深圳
        /// </summary>
        ShenZhen,
        /// <summary>
        /// 北京
        /// </summary>
        BeiJing,
        /// <summary>
        /// 上海
        /// </summary>
        ShangHai
    }
}
